package com.ruoyi.project.erp.service.impl;

import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;

import com.alibaba.excel.EasyExcel;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.common.utils.uuid.UUID;
import com.ruoyi.framework.security.LoginUser;
import com.ruoyi.project.erp.domain.*;
import com.ruoyi.project.erp.dto.*;
import com.ruoyi.project.erp.mapper.ProjectUserMapper;
import com.ruoyi.project.erp.mapper.TaskMapper;
import com.ruoyi.project.erp.mapper.TaskMemberMapper;
import com.ruoyi.project.erp.vo.*;
import com.ruoyi.project.system.domain.SysRole;
import com.ruoyi.project.system.domain.SysUser;
import com.ruoyi.project.system.domain.SysUserRole;
import com.ruoyi.project.system.mapper.SysRoleMapper;
import com.ruoyi.project.system.mapper.SysUserMapper;
import com.ruoyi.project.system.mapper.SysUserRoleMapper;
import com.ruoyi.project.system.service.ISysDeptService;
import com.ruoyi.project.system.service.ISysUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import com.ruoyi.project.erp.mapper.ProjectMapper;
import com.ruoyi.project.erp.service.IProjectService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;

/**
 * 项目Service业务层处理
 *
 * @author ruoyi
 * @date 2025-06-17
 */
@Service
@Slf4j
public class ProjectServiceImpl implements IProjectService {
    @Autowired
    private ProjectMapper projectMapper;
    @Autowired
    private ISysUserService userService;
    @Autowired
    private ISysDeptService deptService;
    @Autowired
    private SysUserMapper userMapper;
    @Autowired
    private SysRoleMapper roleMapper;
    @Autowired
    private SysUserRoleMapper userRoleMapper;
    @Autowired
    private ProjectUserMapper projectUserMapper;

    @Autowired
    private TaskMapper taskMapper;
    @Autowired
    private TaskMemberMapper taskMemberMapper;

    /**
     * 查询项目
     *
     * @param id 项目主键
     * @return 项目
     */
    @Override
    public Project selectProjectById(Long id) {
        return projectMapper.selectProjectById(id);
    }
    @Override
    public ProjectVo selectProjectVoById(Long id, Long userId)
    {
        return projectMapper.selectProjectVoById(id, userId);
    }
    /**
     * 查询项目列表
     *
     * @param project 项目
     * @return 项目
     */
    @Override
    public List<Project> selectProjectList(Project project) {
        return projectMapper.selectProjectList(project);
    }

    /**
     * 新增项目
     *
     * @param project 项目
     * @return 结果
     */
    @Override
    public int insertProject(Project project) {
        project.setCreateTime(DateUtils.getNowDate());
        return projectMapper.insertProject(project);
    }

    /**
     * 修改项目
     *
     * @param project 项目
     * @return 结果
     */
    @Override
    @Transactional // 推荐：因为操作了多张表，使用事务确保数据一致性
    public int updateProject(Project project) {
        project.setUpdateTime(DateUtils.getNowDate());
        Project projectOld = projectMapper.selectProjectById(project.getId());

        // --- 1. 处理项目负责人变更 ---
        // 【修改点 A】使用 Objects.equals 进行 null-safe 比较，防止空指针
        if (!Objects.equals(projectOld.getProjectLeader(), project.getProjectLeader())) {
            // 降级旧的项目负责人（如果存在）
            if (projectOld.getProjectLeader() != null && !projectOld.getProjectLeader().isEmpty()) {
                ProjectUser projectUserOld = projectUserMapper.selectProjectUserByProjectIdAndDdUserId(projectOld.getProjectId(), projectOld.getProjectLeader());
                if (projectUserOld != null) {
                    projectUserOld.setRole("0"); // "0" 代表普通成员
                    projectUserMapper.updateProjectUser(projectUserOld);
                }
            }

            // 提升新的项目负责人（如果存在）
            if (project.getProjectLeader() != null && !project.getProjectLeader().isEmpty()) {
                ProjectUser projectUserNew = projectUserMapper.selectProjectUserByProjectIdAndDdUserId(projectOld.getProjectId(), project.getProjectLeader());
                if (projectUserNew != null) {
                    projectUserNew.setRole("2"); // "2" 代表项目经理
                    projectUserMapper.updateProjectUser(projectUserNew);
                }
                // 思考：如果新的负责人原来不是项目成员，这里是否应该新增一条记录？(根据你的业务需求决定)
            }
        }

        // --- 2. 处理销售负责人变更 ---
        // 【修改点 B】使用 Objects.equals 进行 null-safe 比较，防止空指针
        if (!Objects.equals(projectOld.getSaleId(), project.getSaleId())) {
            // 只有在新销售ID不为空时，才处理后续角色逻辑
            if (project.getSaleId() != null && !project.getSaleId().isEmpty()) {
                SysUser user = userMapper.selectUserByDdUserId(project.getSaleId());

                // 【修改点 C】增加对 user 对象的 null 检查，防止根据不存在的 saleId 查不到用户
                if (user != null) {
                    List<SysUserRole> sysUserRoles = userRoleMapper.selectByUserId(user.getUserId());
                    Long roleId = roleMapper.selectRoleIdByName("销售");

                    // 使用更简洁、安全的 Stream API 判断是否存在
                    boolean isExist = sysUserRoles.stream()
                            .filter(Objects::nonNull) // 过滤掉list中的null元素
                            .anyMatch(userRole -> Objects.equals(userRole.getRoleId(), roleId));

                    if (!isExist) {
                        try {
                            SysUserRole userRole = new SysUserRole();
                            userRole.setRoleId(roleId);
                            userRole.setUserId(user.getUserId());
                            userRoleMapper.insert(userRole);
                        } catch (DuplicateKeyException e) {
                            log.warn("并发插入sys_user_role时发生主键冲突，可安全忽略。UserId: {}, RoleId: {}", user.getUserId(), roleId);
                        }
                    }
                }
            }
        }

        return projectMapper.updateProject(project);
    }

    /**
     * 批量删除项目
     *
     * @param ids 需要删除的项目主键
     * @return 结果
     */
    @Override
    public int deleteProjectByIds(Long[] ids) {
        return projectMapper.deleteProjectByIds(ids);
    }

    /**
     * 删除项目信息
     *
     * @param id 项目主键
     * @return 结果
     */
    @Override
    public int deleteProjectById(Long id) {
        return projectMapper.deleteProjectById(id);
    }

    @Override
    public List<ProjectVo> currentProjects(ProjectDto dto) {
        LoginUser user = SecurityUtils.getLoginUser();
        SysUser reqUser = user.getUser();
        Long adminRoleId = roleMapper.selectRoleIdByName("主管");
        if (dto.getProjectTimeScope()==null){
            dto.setProjectTimeScope("1000");
        }
        switch (dto.getProjectTimeScope()) {
            case "0":
                dto.setProjectTimeScope("1");
                break;
            case "1":
                dto.setProjectTimeScope("6");
                break;
            case "2":
                dto.setProjectTimeScope("12");
                break;
            default:
                dto.setProjectTimeScope("1000");
                break;
        }
        String month = dto.getProjectTimeScope();
        List<ProjectVo> list;
        List<Long> roleIds = reqUser.getRoles().stream().map(SysRole::getRoleId).collect(Collectors.toList());
        if (roleIds.contains(adminRoleId)){
            Long deptId = reqUser.getDeptId();
            // 主管：查本部门所有项目
            list = projectMapper.currentProjectsForLeader(
                    month,
                    deptId,
                    dto.getProjectStatus(),
                    dto.getProjectName(),
                    user.getUser().getDdUserId()
            );
        }else{
            list = projectMapper.currentProjects(
                    month,
                    user.getUser().getDdUserId(),
                    dto.getProjectStatus(),
                    dto.getProjectName()
            );
        }

        list = list.stream().map(x -> {
                    // 这部分逻辑不变
                    x.setProjectLeaderName(userMapper.selectUserByDdUserId(x.getProjectLeader()).getNickName());
                    if (x.getSaleId()==null){
                        x.setSaleName("暂无销售");
                    }else{
                        x.setSaleName(userMapper.selectUserByDdUserId(x.getSaleId()).getNickName());
                    }

                    ProjectUser projectUser = projectUserMapper.selectProjectUserByProjectIdAndDdUserId(x.getProjectId(),reqUser.getDdUserId());

                    // C安全处理，如果用户不在项目里，projectUser可能为null
                    if (projectUser != null) {
                        x.setTop(projectUser.getTop());
                    } else {
                        x.setTop(0); // 默认不置顶
                    }

                    return x;
                })
                // --- 新增排序逻辑 ---
                .sorted(Comparator.comparing(ProjectVo::getTop, Comparator.nullsLast(Comparator.reverseOrder())))
                .collect(Collectors.toList());
        return list;
    }

    @Override
    public ProjectInfoVo queryProjectInfo(String projectId) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        SysUser getUser = loginUser.getUser();
        List<Long> roleIds = roleMapper.selectRoleListByUserId(getUser.getUserId());
        Long role2 = roleMapper.selectRoleIdByName("主管");
        // 查询项目信息
        Project p = projectMapper.selectProjectInfoByProjectId(projectId);
        ProjectInfoVo vo = new ProjectInfoVo();
        BeanUtils.copyBeanProp(vo, p);
        List<SaleVo> sales = new ArrayList<>();
        SaleVo saleVo = new SaleVo();
        if (p.getSaleId()==null){
            saleVo.setName("暂无销售");
        }else{
            saleVo.setSaleId(p.getSaleId());
            SysUser sysUser = userMapper.selectUserByDdUserId(p.getSaleId());
            saleVo.setName(sysUser.getNickName());
        }
        // 查询项目成员
        List<ProjectUser> users = projectUserMapper.selectProjectUserByProjectId(projectId);
        if (users.size() > 0) {
            List<ProjectUserVo> vos = users.stream().map(x -> {
                ProjectUserVo userVo = new ProjectUserVo();
                BeanUtils.copyBeanProp(userVo, x);
                SysUser user = userMapper.selectUserByDdUserId(x.getDdUserId());
                if (user==null){
                    return null;
                }
                userVo.setUserName(user.getNickName());
                userVo.setDdUserId(user.getDdUserId());
                return userVo;
            }).collect(Collectors.toList());
            vo.setProjectUsers(vos);
        }
        //查询任务列表
        Task task = new Task();
        task.setProjectId(projectId);
        List<Task> tasks = taskMapper.selectTaskList(task);
        List<ProjectTaskInfoVo> projectTaskInfoVos = tasks.stream().map(t -> {
            ProjectTaskInfoVo taskVo = new ProjectTaskInfoVo();
            BeanUtils.copyProperties(t, taskVo);
            // 查询该任务的成员
            List<String> taskUserDingIds = taskMemberMapper.selectTaskUserByTaskId(t.getId());
            List<TaskUserVo> taskUserVos = taskUserDingIds.stream().map(dingId -> {
                TaskUserVo userVo = new TaskUserVo();
                SysUser user = userMapper.selectUserByDdUserId(dingId);
                userVo.setDdUserId(user.getDdUserId());
                userVo.setUserName(user.getNickName());
                return userVo;
            }).collect(Collectors.toList());
            taskVo.setTaskUserVos(taskUserVos);
            return taskVo;
        }).collect(Collectors.toList());
        vo.setTasks(projectTaskInfoVos);
        sales.add(saleVo);
        vo.setSales(sales);
        if (roleIds.contains(role2)||(p.getSaleId()!=null && p.getSaleId().equals(getUser.getDdUserId()))|| p.getProjectLeader().equals(getUser.getDdUserId())){
            vo.setCanEditProject(true);
        }else{
            vo.setCanEditProject(false);
        }
        return vo;
    }

    @Override
    public List<MyProjectInfoVo> getMyProject(SysUser user) {
        String dingId = user.getDdUserId();
//        List<String> projectIds = projectUserMapper.selectProjectByDingId(dingId);
//        return projectMapper.selectProjectByIds(projectIds);

        return projectMapper.selectMyProject(dingId);
    }

    @Override
    public int createProject(CreateProjectDto dto) {
        Project project = new Project();
        BeanUtils.copyBeanProp(project, dto);
        project.setCreateTime(DateUtils.getNowDate());
        SysUser projectLeader = userMapper.selectUserByDdUserId(dto.getProjectLeader());
        project.setDeptId(projectLeader.getDeptId());
        int i = projectMapper.insertProject(project);


        Task task = new Task();
        String taskCode = UUID.randomUUID().toString().substring(0,6);
        task.setTaskCode("TASK"+taskCode.toUpperCase());
        task.setStatus("1");
        task.setProjectId(project.getProjectId());
        task.setPriority("0");
        task.setStartTime(project.getProjectStartTime());
        task.setEndTime(project.getProjectEndTime());
        task.setTaskName(project.getProjectName()+"基本工作");
        taskMapper.insertTask(task);
        if (i <= 0) {
            throw new ServiceException("项目创建失败，请稍后再试");
        }
        //判断项目成员表中是否有项目经理
        includeUsers(dto, dto.getProjectLeader(), "2");
        //判断项目成员表中是否有销售
        includeUsers(dto, dto.getSaleId(), "1");

        // 新增项目成员
        if (dto.getProjectUserList() != null) {
            List<ProjectUser> projectUsers = dto.getProjectUserList().stream().map(x -> {
                ProjectUser pu = new ProjectUser();
                pu.setDdUserId(x.getDdUserId());
                pu.setProjectId(project.getProjectId());
                pu.setJobGrade(x.getJobGrade());
                return pu;
            }).collect(Collectors.toList());
            projectUsers.forEach(x -> {
                x.setCreateTime(DateUtils.getNowDate());
                projectUserMapper.insertProjectUser(x);
                TaskMember taskMember = new TaskMember();
                taskMember.setTaskId(task.getId());
                taskMember.setUserId(x.getDdUserId());
                taskMember.setCreateTime(DateUtils.getNowDate());
                taskMemberMapper.insertTaskMember(taskMember);
            });


        }


        SysUser user = userMapper.selectUserByDdUserId(dto.getSaleId());
        List<Long> roles = roleMapper.selectRoleListByUserId(user.getUserId());
        Long role = roleMapper.selectRoleIdByName("销售");
        if (!roles.contains(role)){
            SysUserRole userRole = new SysUserRole();
            userRole.setUserId(user.getUserId());
            userRole.setRoleId(role);
            userRoleMapper.insert(userRole);
        }

        return 1;
    }

    @Override
    public int editProject(CreateProjectDto dto) {
        Project project = new Project();
        project.setUpdateTime(DateUtils.getNowDate());
        BeanUtils.copyBeanProp(project, dto);
        projectMapper.updateProject(project);

        List<ProjectUser> oldProjectUsers = projectUserMapper.selectProjectUserByProjectId(dto.getProjectId());
        // 删除原有的项目成员
        if (!CollectionUtils.isEmpty(oldProjectUsers)) {
            projectUserMapper.deleteProjectUserByProjectId(project.getProjectId());
        }
        if (dto.getProjectUserList() == null && dto.getProjectUserList().size() == 0) {
            throw new ServiceException("项目成员不能为空，请添加项目成员");
        }
        //判断项目成员表中是否有项目经理
        includeUsers(dto, dto.getProjectLeader(), "2");
        //判断项目成员表中是否有销售
        includeUsers(dto, dto.getSaleId(), "1");

        // 新增项目成员
        if (!CollectionUtils.isEmpty(dto.getProjectUserList())) {
            List<ProjectUser> projectUsers = dto.getProjectUserList().stream().map(x -> {
                ProjectUser pu = new ProjectUser();
                pu.setDdUserId(x.getDdUserId());
                pu.setProjectId(project.getProjectId());
                pu.setJobGrade(x.getJobGrade());
                pu.setStatus("1");
                return pu;
            }).collect(Collectors.toList());
            projectUsers.forEach(x -> {
                x.setCreateTime(DateUtils.getNowDate());
                projectUserMapper.insertProjectUser(x);
            });
        }
        return 1;
    }

    @Override
    public List<Project> getUserProjectInfo(String userId) {
        List<ProjectUser> projectUsers = projectUserMapper.selectProjectListByUserId(userId);
        return projectUsers.stream().map(w-> projectMapper.selectProjectInfoByProjectId(w.getProjectId())).collect(Collectors.toList());
    }

    @Override
    public List<Project> selectAllProject() {
        return projectMapper.selectAllProjects();
    }

    @Override
    public String importProject(InputStream inputStream, boolean isUpdateSupport, String operName) { // 增加 operName 参数
        if (inputStream == null) {
            throw new ServiceException("导入文件不能为空");
        }

        // 将 operName 传递给 Listener 的构造函数
        ProjectDataListener listener = new ProjectDataListener(
                projectMapper,
                projectUserMapper,
                userService,
                deptService,
                isUpdateSupport,
                operName // 新增的参数
        );

        try {
            EasyExcel.read(inputStream, ProjectExcelVo.class, listener).sheet().doReadSync();
        } catch (Exception e) {
            throw new ServiceException("导入处理过程中发生错误: " + e.getMessage());
        } finally {
            // ... 关闭流
        }

        return listener.getSummary();
    }

    @Override
    public List<ProjectVo> selectList(ProjectQuery query) {
        return projectMapper.selectList(query);
    }

    @Override
    public List<ProjectListVO> getMyProjectByDate(Date date) {
// 1. 从安全上下文中获取当前登录的用户信息
        // RuoYi的LoginUser中通常会包含完整的SysUser对象
        SysUser currentUser = SecurityUtils.getLoginUser().getUser();
        String ddUserId = currentUser.getDdUserId(); // 获取钉钉用户ID

        // 如果没有dd_user_id，则直接返回空列表，避免查询错误
        if (ddUserId == null || ddUserId.isEmpty()) {
            return Collections.emptyList();
        }

        // 2. 调用Mapper方法进行数据库查询
        return projectMapper.selectMyActiveProjectsByDate(ddUserId, date);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void addProjectBySales(AddProjectBySalesDTO addProjectBySalesDTO) {
        String projectId = addProjectBySalesDTO.getSaleId();
        Project project = new Project();
        BeanUtils.copyProperties(addProjectBySalesDTO,project);
        if (project.getProjectEndTime() == null){

        }
        SysUser projectLeader = userMapper.selectUserByDdUserId(project.getProjectLeader());
        project.setDeptId(projectLeader.getDeptId());
        SysUser sales = userMapper.selectUserByDdUserId(addProjectBySalesDTO.getSaleId());
        Project project1 = projectMapper.selectProjectByName(sales.getNickName());
        if (project1 != null && !ObjectUtils.isEmpty(project1) ){
            throw new ServiceException("项目已存在，请勿重复添加！");
        }

        project.setProjectName(sales.getNickName());
        project.setProjectId(projectId);
        project.setCreateBy(SecurityUtils.getUsername());
        projectMapper.insertProject(project);


        List<ProjectUser> projectUsers = addProjectBySalesDTO.getDdUserId().stream().map(w->{
            ProjectUser projectUser = new ProjectUser();
            if (w.equals(addProjectBySalesDTO.getSaleId())){
                projectUser.setRole("0");
                projectUser.setDdUserId(w);
                projectUser.setStatus("1");
                projectUser.setProjectId(projectId);
                return projectUser;
            }else if (w.equals(addProjectBySalesDTO.getProjectLeader())){
                projectUser.setRole("2");
                projectUser.setDdUserId(w);
                projectUser.setStatus("1");
                projectUser.setProjectId(projectId);
                return projectUser;
            }
            projectUser.setRole("0");
            projectUser.setDdUserId(w);
            projectUser.setStatus("1");
            projectUser.setProjectId(projectId);
            return projectUser;
        }).collect(Collectors.toList());
        projectUserMapper.batchInsertProjectUser(projectUsers);
    }

    /**
     *  是否包含用户
     * @param dto
     * @param userId
     * @param role
     */
    private static void includeUsers(CreateProjectDto dto, String userId, String role) {
        boolean cc = dto.getProjectUserList().stream()
                                            .map(x -> x.getDdUserId())
                                            .collect(Collectors.toList()).contains(userId);
        if (!cc){
            ProjectUserDto userDto = new ProjectUserDto();
            userDto.setDdUserId(userId);
            userDto.setJobGrade(role);
            dto.getProjectUserList().add(userDto);
        }
    }
}
